package com.ekang.admin.web;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ekang.admin.config.WechatConfig;
import com.ekang.admin.model.Order;
import com.ekang.admin.service.GoodsService;
import com.ekang.wxpay.base.model.PayResult;
import com.ekang.wxpay.base.model.enums.ResultCode;
import com.ekang.wxpay.model.PayNotifyResult;
import com.ekang.wxpay.model.PayOrderParam;
import com.ekang.wxpay.model.PayOrderResult;
import com.ekang.wxpay.model.enums.PayOrderField;
import com.ekang.wxpay.util.*;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

/**
 * 在微信浏览器中，h5页面调起
 */
@Controller
@RequestMapping("/h5pay")
public class WeixinH5PayController {

    private static Log logger = LogFactory.getLog(WeixinH5PayController.class);


    @Autowired
    GoodsService goodsService;

    @Autowired
    WechatConfig wechatConfig;

    // pay 微信支付商户号
    String mchId = null;// WebPropertiesUtil.getInstance().getValue("weixin.mchid"); //"1410549802";

    //mp.weixin  微信mini appId
    String appId = null;//WebPropertiesUtil.getInstance().getValue("weixin.appid"); //"wx3373f34a5f886c93";


    //mp.weixin  微信mini appId
    String secret = null;//WebPropertiesUtil.getInstance().getValue("weixin.secret"); //"wx3373f34a5f886c93";

    // 申请开通微信支付后，发给开发者。用于计算签名
    String apiKey = null;//WebPropertiesUtil.getInstance().getValue("weixin.pay.apikey");//"kVsKpZC6HN4jzNSM5RnZo7s2M1KpD614"

    // 微信支付 统一下单接口
    String payOrderUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";  //WebPropertiesUtil.getInstance().getValue("weixin.pay.unifiedorder");

    // 支付 回调url
    String notifyUrl = null;
    // WebPropertiesUtil.getInstance().getValue("weixin.pay.notify_url") + "/h5pay/notify"; //"http://gzbankweb.gcn99.com/dc";//


    /**
     * 获取支付需要的openID
     *
     * @param code
     * @return
     */
    @RequestMapping(value = "/openId", method = RequestMethod.GET, produces = {"application/json;charset=UTF-8"})
    @ResponseBody
    public String getOpenId(@RequestParam("code") String code) {
        String requestUrl = "https://api.weixin.qq.com/sns/jscode2session?appid=" + wechatConfig.getAppId() + "&secret=" + wechatConfig.getSecret() + "&js_code=" + code + "&grant_type=authorization_code";
        String result = null;
        HttpClient client = null;
        try {
            client = new DefaultHttpClient();
            HttpGet httpget = new HttpGet(requestUrl);
            ResponseHandler<String> responseHandler = new BasicResponseHandler();
            String response = client.execute(httpget, responseHandler);
            JSONObject OpenidJSONO = JSONObject.parseObject(response);

            logger.info("OpenidJSONO===" + OpenidJSONO.toString());

            result = String.valueOf(OpenidJSONO.get("openid"));
            if (StringUtils.isEmpty(result)) {
                throw new Exception("获取openid失败");
            }

        } catch (Exception e) {
            e.printStackTrace();

        } finally {
            client.getConnectionManager().shutdown();
        }
        return result;
    }


    /**
     * 微信统一下单
     *
     * @param orderParam
     * @return
     */
    @RequestMapping(value = "/do", method = RequestMethod.POST, produces = {"application/json;charset=UTF-8"})
    @ResponseBody
    public String payDo(@RequestBody PayOrderParam orderParam) {
        mchId = wechatConfig.getMchId();
        appId = wechatConfig.getAppId();
        apiKey = wechatConfig.getApiKey();
        notifyUrl = wechatConfig.getNotifyUrl() + "/h5pay/notify";

        PayOrderParam param = new PayOrderParam();
        // 基本信息
        param.setAppid(appId);
        param.setMchId(mchId);
        param.setTradeType("JSAPI"); // 公众号支付 JSAPI
        param.setOpenid(orderParam.getOpenid()); // openId!!
        param.setSpbillCreateIp(LocalIPUtil.getLocalAddr());
        param.setNotifyUrl(notifyUrl); // 支付成功回调url
        param.setAttach(orderParam.getAttach()); // atach.toString());
        param.setBody(orderParam.getBody());
        param.setTotalFee(orderParam.getTotalFee());
        param.setOutTradeNo(orderParam.getOutTradeNo()); // 客户订单号
        //测试环境支付1分
        if ("0".equalsIgnoreCase(wechatConfig.getOnline())) {
            param.setTotalFee(1);
        }

        //签名
        param.setNonceStr(EncryptUtil.random());
        Map<String, Object> data = BeanUtil.object2Map(param); // 参数列表
        param.setSign(SignUtil.sign(data, apiKey)); // 计算sign
        data.put(PayOrderField.SIGN.getField(), param.getSign()); // sign放到map中，为后续转xml

        // 校验参数是否齐全
        try {
            ValidateUtil.validate(PayOrderField.values(), data);
        } catch (Exception e) {
            return JsonUtil.getJson(1, e.getMessage()).toString();
        }

        // 转成xml格式
        String xml = XmlUtil.toXml(data);
        logger.info("post.xml=" + xml);
        // 发送支付请求
        String resultStr = WeixinUtil.postXml(payOrderUrl, xml);
        logger.info("result=" + resultStr);

        // 校验返回结果 签名
        Map<String, Object> resultMap = XmlUtil.parseXml(resultStr);
        String resultSign = SignUtil.sign(resultMap, apiKey);
        if (resultMap.get("sign") == null || !resultMap.get("sign").equals(resultSign)) {
            logger.info("sign is not correct, " + resultMap.get("sign") + " " + resultSign);
            throw new RuntimeException("签名校验不通过");
        }

        PayOrderResult result = BeanUtil.map2Object(PayOrderResult.class, resultMap);

        PayResult payResult = new PayResult();
        if (ResultCode.SUCCESS.getCode().equals(result.getReturnCode())
                && ResultCode.SUCCESS.getCode().equals(result.getResultCode())) {
            payResult.setResultCode(ResultCode.SUCCESS.getCode());
        } else {
            payResult.setResultCode(ResultCode.FAIL.getCode());
        }
        payResult.setMessage(result.getReturnMsg());
        payResult.setErrCode(result.getErrCode());
        payResult.setErrorMessage(result.getErrCodeDes());
        payResult.setPrepayId(result.getPrepayId());
        payResult.setCodeUrl(result.getCodeUrl());

        JSONObject ret = JsonUtil.getOkJson();
        ret.put("result", payResult);
        ret.put("param", genJsParam(payResult));

        //update order to db
        Order order = new Order();
        order.setOrderNO(orderParam.getOutTradeNo());
        order.setWxOrderNO(payResult.getPrepayId());
        goodsService.updateOrder(order);

        return ret.toString();
    }


    /**
     * 微信支付成功通知接口
     *
     * @param request
     * @return
     */
    @RequestMapping(value = "/notify", produces = {"application/json;charset=UTF-8"})
    @ResponseBody
    public String notify(HttpServletRequest request) {
        try {
            mchId = wechatConfig.getMchId();
            appId = wechatConfig.getAppId();
            apiKey = wechatConfig.getApiKey();
            notifyUrl = wechatConfig.getNotifyUrl() + "/h5pay/notify";

            String xml = IOUtils.toString(request.getInputStream());
            logger.info("weixin pay notify result is " + xml);
            if (StringUtils.isBlank(xml)) {
                return WeixinUtil.getResult(ResultCode.FAIL, "接受参数为空");
            }
            Map<String, Object> map = XmlUtil.parseXml(xml);
            PayNotifyResult result = BeanUtil.map2Object(PayNotifyResult.class, map);
            logger.info(JSON.toJSONString(result, true));
            Order order = new Order();
            order.setOrderNO(result.getOutTradeNo());
            order.setStatus(1);
            goodsService.updateOrderPayed(order);

        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return WeixinUtil.getResult(ResultCode.FAIL, "解析异常");
        }
        return WeixinUtil.getResult(ResultCode.SUCCESS, "OK");
    }

    private JSONObject genJsParam(PayResult payResult) {
        long timestamp = System.currentTimeMillis() / 1000;
        String nonceStr = EncryptUtil.random();

        Map<String, Object> data = new HashMap<String, Object>();
        data.put("appId", appId);
        data.put("timeStamp", timestamp);
        data.put("nonceStr", nonceStr);
        data.put("package", "prepay_id=" + payResult.getPrepayId());
        data.put("signType", "MD5");

        data.put("paySign", SignUtil.sign(data, apiKey)); // 计算sign

        JSONObject ret = JSONObject.parseObject(JSON.toJSONString(data));
        return ret;
    }





}
